package threadPoolDemo;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: Jie
 * @Date: 2019/4/11 17:32
 * @Function : 测试线程池 之间线程是否是 同时并发, create  shutdown threadpool
 * 结论： newFixedThreadPool 并发,执行。
 * <p>
 * 阿里，禁止用.
 * 原因：
 * <p>
 * 1.
 * public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
 * LinkedBlockingQueue,且没有指定容量，相当于无界队列，这种情况下就可以添加大量的任务，甚至达到Integer.MAX_VALUE的数量级，如果任务大量堆积，可能会导致 OOM。
 * <p>
 * CachedThreadPool的创建方法如下：public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
 * 这个虽然使用了有界队列SynchronousQueue，但是最大线程数设置成了Integer.MAX_VALUE，这就意味着可以创建大量的线程，也有可能导致 OOM。
 * <p>
 * <p>
 * TODO 最佳实践
 *  最好用 main(String[] args) {
 *  @Test 对线程池，执行任务有影响，
 *  @see CreateThreadPool#main(java.lang.String[])
 */
public class CreateThreadPool {
    private static final Logger logger = Logger.getLogger(CreateThreadPool.class);

    //TODO 最佳实践 guava jar ThreadFactory
    public static ExecutorService createThreadPool(String poolname,int coreSize, int maxPoolSize,long keepAliveTime,TimeUnit timeUnit,BlockingQueue<Runnable> blockingQueue){
        ThreadFactory guavaThreadFactory = new ThreadFactoryBuilder().setNameFormat(poolname+"-%d").build();

        return new ThreadPoolExecutor(coreSize, maxPoolSize,
                keepAliveTime, timeUnit,
                blockingQueue, guavaThreadFactory);
    }

    //TODO 第二种 自定义ThreadFactory
    @Test
    public void createCustomerThreadPool() {
        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger mCount = new AtomicInteger(1);

            @Override
            public Thread newThread(Runnable runnable) {
                return new Thread(runnable, "my-customer-threadpool-" + mCount.getAndIncrement());
            }
        };

        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 2000L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(100), threadFactory);


        executorService.execute(()->{
            logger.info("createCustomerThreadPool:-----> 第一个任务"  + Thread.currentThread().getName());
        });

//        for (int i = 1; i < 120; i++) {//超过了最大值 抛出异常 103个任务是 时。thread 2+ queue +100.
//        java.util.concurrent.RejectedExecutionException: Task threadPoolDemo.CreateThreadPool$$Lambda$1/1690716179@25618e91
//        rejected from java.util.concurrent.ThreadPoolExecutor@7a92922[Running, pool size = 2, active threads = 2, queued tasks = 100, completed tasks = 0]
        for (int i = 1; i < 80; i++) {
            logger.info("createCustomerThreadPool: fori " + i);
            int finalI = i;
            executorService.execute(() -> {
                try {
                    logger.info("createCustomerThreadPool:-----> " + finalI + Thread.currentThread().getName());
                    Thread.sleep(2);
                    logger.info("createCustomerThreadPool:over " + finalI + Thread.currentThread().getName());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

    }

    @Test
    public void createThreadPoolExecutors() {
        Executors.newCachedThreadPool();
        Executors.newFixedThreadPool(1);
        Executors.newSingleThreadExecutor();
        Executors.newScheduledThreadPool(1);
        Executors.newWorkStealingPool(1);
    }

    //TODO 第一种 Google guava 工具类 提供的 ThreadFactoryBuilder ,使用链式方法创建。
    // 拒绝策略
//maven 下载地址
//       <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
//<dependency>
//  <groupId>com.google.guava</groupId>
//  <artifactId>guava</artifactId>
//  <version>28.2-jre</version>
//</dependency>
//    @Test
    public void createThreadPoolGoogle() {
//    public static void main1(String[] args) {
        ThreadFactory guavaThreadFactory = new ThreadFactoryBuilder().setNameFormat("guava-pool-%d").build();

        ExecutorService executorService = new ThreadPoolExecutor(1, 2,
                200L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(100), guavaThreadFactory);

        executorService.submit(() -> {
            logger.info("--记忆中的颜色是什么颜色---");
        });

//        for (int i = 1; i < 120; i++) {//超过了最大值 抛出异常 103个任务是 时。thread 2+ queue +100.
//        java.util.concurrent.RejectedExecutionException: Task threadPoolDemo.CreateThreadPool$$Lambda$1/1690716179@25618e91
//        rejected from java.util.concurrent.ThreadPoolExecutor@7a92922[Running, pool size = 2, active threads = 2, queued tasks = 100, completed tasks = 0]

        for (int i = 1; i < 80; i++) {
            logger.info("createCustomerThreadPool: fori " + i);
            int finalI = i;
            executorService.execute(() -> {
                try {
                    logger.info("createCustomerThreadPool:-----> " + finalI + Thread.currentThread().getName());
                    Thread.sleep(10);
                    logger.info("createCustomerThreadPool:over " + finalI + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        //TODO  拒绝策略后的线程池：
        try {

            TimeUnit.SECONDS.sleep(4);
            logger.info("createCustomerThreadPool:last task " + Thread.currentThread().getName());
            logger.info("main: isTerminated:"+executorService.isTerminated()+" isShutDown:"+executorService.isShutdown());
            executorService.submit(()->{
                logger.info("createCustomerThreadPool:last task " + Thread.currentThread().getName());

            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


//    @Test
//    public void shutdownThreadPool(){
    public static void mainShutdown(String[] args) {
        ExecutorService shutdownpool = createThreadPool("shutdownpool", 1, 5, 200L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(5));

        for (int i = 0; i < 10; i++) {
            try {

                int finalI = i;
                shutdownpool.execute(()->{
                    logger.info("shutdownThreadPool: exec task "+ finalI);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    logger.info("shutdownThreadPool: exec task "+ finalI+"  over");

                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        shutdownpool.shutdown();//会把队列的任务执行完毕。后续加入的任务， 抛出RejectedExecutionException
//        shutdownpool.shutdownNow();//不推荐 中断所有任务，并停止接受新任务
    }


    @Test
    public void testPoolMutilThreadRun() {
        ExecutorService pool = Executors.newFixedThreadPool(4);
        Runnable run1 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("run1----" + i);
//                    try {
//                        Thread.sleep(1);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                }
            }
        };
        Runnable run2 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.err.println("run2****" + i);
//                    try {
//                        Thread.sleep(1);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                }
            }
        };

        pool.execute(run1);
        pool.execute(run2);
    }


}
